package com.jonluo.uploader.service;


import com.jonluo.uploader.exception.StorageException;
import com.jonluo.uploader.exception.StorageFileNotFoundException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.stereotype.Service;
import org.springframework.util.FileSystemUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.net.MalformedURLException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Iterator;
import java.util.UUID;
import java.util.stream.Stream;

@Service
public class StorageServiceImpl implements StorageService {

    @Value("${file.upload.location.path}")
    private String rootDir;

    // 图片允许格式
    @Value("${file.upload.allow.photos.ext}")
    private static String allowPhotos;
    // 文件允许格式
    @Value("${file.upload.allow.files.ext}")
    private static String allowFiles;
    /**
     *存储文件
     * @param file
     */
    @Override
    public String store(MultipartFile file, String flieNamePre) {
        String uploadFileName = file.getOriginalFilename();
        /*新文件名*/
        uploadFileName = parseNewName(uploadFileName,flieNamePre);
        try {
            if (file.isEmpty()) {
                throw new StorageException("Failed to store empty file " + file.getOriginalFilename());
            }
            /**
             * 将文件流复制到文件下
             */
            Files.copy(file.getInputStream(), getRootPath().resolve(uploadFileName));
        } catch (IOException e) {
            throw new StorageException("Failed to store file " +uploadFileName, e);
        }
        return uploadFileName;
    }

    /**
     * 获取所有文件的物理路径
     * @return
     */
    @Override
    public Stream<Path> loadAll() {
        try {
            return Files.walk(getRootPath(), 1)
                    .filter(path -> !path.equals(getRootPath()))
                    .map(path -> getRootPath().relativize(path));
        } catch (IOException e) {
            throw new StorageException("Failed to read stored files", e);
        }

    }

    /**
     * 获取物理路径
     * @param filename
     * @return
     */
    @Override
    public Path load(String filename) {
        return getRootPath().resolve(filename);
    }

    /**
     * 根据物理路径生成资源
     * @param filename
     * @return
     */
    @Override
    public Resource loadAsResource(String filename) {
        try {
            Path file = load(filename);
            Resource resource = new UrlResource(file.toUri());
            if(resource.exists() || resource.isReadable()) {
                return resource;
            }
            else {
                throw new StorageFileNotFoundException("Could not read file: " + filename);
            }
        } catch (MalformedURLException e) {
            throw new StorageFileNotFoundException("Could not read file: " + filename, e);
        }
    }

    /**
     * 清空文件夹
     */
    @Override
    public void deleteAll() {
        FileSystemUtils.deleteRecursively(getRootPath().toFile());
    }

    /**
    * 根据文件名删除物理路径文件
    * @param filename
    * @return
    */
    @Override
    public void deleteByName(String filename) {
        Path file = load(filename);
        try {
            Files.deleteIfExists(file);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    /**
     * 初始化
     */
    @Override
    public void init() {
        getRootPath();
    }

    /**
     * 创建根文件夹
     * 并返回路径
     * @return Path
     */
    private Path getRootPath() {
        Path p = null;
        try {
             p = Paths.get(rootDir);
            if (!Files.exists(p)){
                Files.createDirectory(p);
            }
        } catch (IOException e) {
            throw new StorageException("Could not initialize storage", e);
        }
        return p;
    }



    /**
     * 文件类型判断
     * @param fileName
     * @param fileType file文件 photo图片
     * @return
     */
    private boolean checkFileType(String fileName ,String fileType) {
        String[] fileExt = null;
        if ("file".equals(fileType)){
            fileExt = allowFiles.split(",");
        }else {
            fileExt = allowPhotos.split(",");
        }
        Iterator<String> type = Arrays.asList(fileExt).iterator();
        while (type.hasNext()) {
            String ext = type.next();
            if (fileName.toLowerCase().endsWith(ext)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 依据原始文件名生成新文件名
     * @param oldName
     * @param pre  生成文件名前缀
     * @return
     */
    private String parseNewName(String oldName, String pre) {
        String fileExt = oldName.substring(oldName.lastIndexOf("."));
        String newName = pre+"-"+ UUID.randomUUID().toString().replace("-","")+fileExt;
        return  newName;
    }

}
